package com.linran.utils.office.world;


import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTUnderline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STUnderline;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * https://zhuanlan.zhihu.com/p/150676300?utm_source=qq&utm_medium=social&utm_oi=1033657022440407040
 */
public class WordUtil {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            long startTime = System.currentTimeMillis();
            File file = new File("C:\\Users\\Admin\\Desktop\\new1.docx");
            // docx 文档的高级类对象
            XWPFDocument document = null;
            InputStream in = null;
            try(FileOutputStream ops = new FileOutputStream(file)) {
                in = new ClassPathResource("合约模板.docx").getInputStream();
                //获取docx解析对象
                document = new XWPFDocument(in);

                //准备参数
                Map<String, String> replaceMap = new HashMap();

                replaceMap.put("owner", "测试甲方名称");
                replaceMap.put("partyB", "测试乙方名称");
                replaceMap.put("city", "成都市");
                replaceMap.put("street", "双桥路");
                replaceMap.put("lane", "玉双路");
                replaceMap.put("no", "66");
                replaceMap.put("ridgepole", "9");
                replaceMap.put("room", "01");
                replaceMap.put("buildSqr", "120");
                replaceMap.put("useSqr", "100");
                replaceMap.put("type", "商用");
                replaceMap.put("struct", "三级");
                replaceMap.put("damage", "二级");
                replaceMap.put("facility", "普通用具");
                replaceMap.put("use", "衣物经销");
                replaceMap.put("rentMonth", "24");
                replaceMap.put("startYear", "2020");
                replaceMap.put("startMonth", "11");
                replaceMap.put("startDay", "07");
                replaceMap.put("endYear", "2020");
                replaceMap.put("endMonth", "11");
                replaceMap.put("endDay", "07");
                replaceMap.put("relayMonth", "3");
                replaceMap.put("rentCash", "2400");
                replaceMap.put("deliMonth", "11");
                replaceMap.put("legal", "法人小明");
                replaceMap.put("legalProxy", "法人小红");
                replaceMap.put("delegate", "委托人小海");
                replaceMap.put("delegateProxy", "委托人小华");


                changeText(document, replaceMap);


                document.write(ops);
                System.out.printf("耗时:%d \r\n", System.currentTimeMillis() - startTime);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*下载会使用到*/

    private void downloadReportFile(String templatePath, String fileName, Map<String, String> replaceMap, List<String[]> list1, List<String[]> list2, HttpServletResponse response) {
        XWPFDocument document = null;
        InputStream in = null;
        //生成新的word
        response.reset();
        response.setContentType("application/x-msdownload");

        ByteArrayOutputStream ostream = new ByteArrayOutputStream();
        OutputStream os = null;

        try {
            response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

            in = new ClassPathResource(templatePath).getInputStream();
            //获取docx解析对象
            document = new XWPFDocument(in);
            //解析替换文本段落对象
            WordUtil.changeText(document, replaceMap);
            //解析替换表格对象
            List<XWPFTable> tables = document.getTables();
            if (tables != null && tables.size() > 1) {
                //第一个表格
                WordUtil.insertTable(tables.get(0),list1);
                //第二个表格
                WordUtil.insertTable(tables.get(1), list2);
            }
            os = response.getOutputStream();
            document.write(os);
            os.write(ostream.toByteArray());
            os.close();
            ostream.close();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (document != null) {
                    document.close();
                }
                if (os != null) {
                    os.close();
                }
                if (ostream != null) {
                    ostream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 替换段落文本
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeText(XWPFDocument document, Map<String, String> textMap) {
        //获取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            //获取到段落中的所有文本内容
            String text = paragraph.getText();
            //判断此段落中是否有需要进行替换的文本
            if (checkText(text)) {
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    //替换模板原来位置
                    run.setText(changeValue(run.toString(), textMap), 0);
                }
            }
        }
    }

    /**
     * 判断文本中是否包含$
     *
     * @param text 文本
     * @return 包含返回true, 不包含返回false
     */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.indexOf("$") != -1) {
            check = true;
        }
        return check;
    }

    /**
     * 匹配传入信息集合与模板
     *
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String changeValue(String value, Map<String, String> textMap) {
        Set<Map.Entry<String, String>> textSets = textMap.entrySet();
        for (Map.Entry<String, String> textSet : textSets) {
            //匹配模板与替换值 格式${key}
            String key = "${" + textSet.getKey() + "}";
            if (value.indexOf(key) != -1) {
                value = value.replaceAll("\\$\\{"+textSet.getKey()+"\\}",textSet.getValue());
            }
        }
        //模板未匹配到区域替换为空
        if (checkText(value)) {
            value = "";
        }
        return value;
    }

    /**
     * 为表格插入数据，行数不够添加新行
     *
     * @param table     需要插入数据的表格
     * @param tableList 插入数据集合
     */
    public static void insertTable(XWPFTable table, List<String[]> tableList) {
        //创建行,根据需要插入的数据添加新行，不处理表头
        for (int i = 1; i < tableList.size(); i++) {
            table.createRow();
        }
        //遍历表格插入数据
        List<XWPFTableRow> rows = table.getRows();
        for (int i = 1; i < rows.size(); i++) {
            XWPFTableRow newRow = table.getRow(i);
            List<XWPFTableCell> cells = newRow.getTableCells();
            for (int j = 0; j < cells.size(); j++) {
                XWPFTableCell cell = cells.get(j);
                cell.setText(tableList.get(i - 1)[j]);
            }
        }
    }

    public static void underLine(XWPFRun pRun, int underLineStyle) {
        CTRPr pRpr = null;
        if (pRun.getCTR() != null) {
            pRpr = pRun.getCTR().getRPr();
            if (pRpr == null) {
                pRpr = pRun.getCTR().addNewRPr();
            }
        }

        CTUnderline u = pRpr.isSetU() ? pRpr.getU() : pRpr.addNewU();
        u.setVal(STUnderline.Enum.forInt(Math.abs(underLineStyle % 19)));
        //u.setColor(underLineColor);
    }

}
